/*
 * @(#)RegistryObjectListTransformer.java
 * Date 2013-09-02
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.transformer.xds;

import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import javax.xml.bind.JAXBElement;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.AssociationType1;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.ExtrinsicObjectType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.IdentifiableType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.ObjectRefType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.RegistryObjectListType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.RegistryPackageType;

import org.apache.commons.lang3.StringUtils;

import us.hornerscorners.lamppost.exception.ServiceActionException;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;

import us.hornerscorners.lamppost.model.document.Association;
import us.hornerscorners.lamppost.model.document.DocumentEntry;
import us.hornerscorners.lamppost.model.document.Folder;
import us.hornerscorners.lamppost.model.document.SubmissionSet;

import us.hornerscorners.lamppost.registry.constant.QueryReturnModelType;

import us.hornerscorners.lamppost.registry.model.QueryRequest;
import us.hornerscorners.lamppost.registry.model.QueryResponse;
import us.hornerscorners.lamppost.registry.model.QueryReturnType;
import us.hornerscorners.lamppost.registry.model.RegistryObjects;

import us.hornerscorners.lamppost.registry.utils.XDSUtils;

import us.hornerscorners.lamppost.transformer.AbstractTransformer;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-09-02
 * @author         Jim Horner
 */
@ApplicationScoped
public class RegistryObjectListTransformer
        extends AbstractTransformer<QueryResponse, RegistryObjectListType> {

    /** Field description */
    @Inject
    private AssociationTypeTransformer associationTransformer;

    /** Field description */
    @Inject
    private IHEConfig config;

    /** Field description */
    @Inject
    private DocumentEntryTypeTransformer documentEntryTransformer;

    /** Field description */
    @Inject
    private FolderTypeTransformer folderTransformer;

    /** Field description */
    @Inject
    private SubmissionSetTypeTransformer submissionSetTransformer;

    /**
     * Constructs ...
     *
     */
    public RegistryObjectListTransformer() {
        super();
    }

    /**
     * Method description
     *
     *
     *
     * @param response
     * @return
     * @throws us.hornerscorners.lamppost.exception.ServiceActionException
     */
    @Override
    public RegistryObjectListType transform(QueryResponse response)
            throws ServiceActionException {

        RegistryObjectListType result = new RegistryObjectListType();

        RegistryObjects rol = response.getRegistryObjects();
        QueryRequest request = response.getQueryRequest();
        boolean leaf = (request.getReturnType() == QueryReturnType.LeafClass);

        for (QueryReturnModelType returnType :
                request.getQueryMethodConfig().getReturnTypes()) {

            if (QueryReturnModelType.DocumentEntry.equals(returnType)) {

                for (DocumentEntry doc : rol.getDocumentEntries()) {

                    if (leaf) {

                        ExtrinsicObjectType docType =
                            this.documentEntryTransformer.transform(doc);

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createExtrinsicObject(docType));

                    } else {

                        ObjectRefType objRef = new ObjectRefType();

                        objRef.setId(doc.getEntryURN());

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createObjectRef(objRef));
                    }
                }

            } else if (QueryReturnModelType.Folder.equals(returnType)) {

                for (Folder folder : rol.getFolders()) {

                    if (leaf) {

                        RegistryPackageType regPack =
                            this.folderTransformer.transform(folder);

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createRegistryPackage(regPack));

                    } else {

                        ObjectRefType objRef = new ObjectRefType();

                        objRef.setId(folder.getEntryURN());

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createObjectRef(objRef));
                    }
                }

            } else if (QueryReturnModelType.SubmissionSet.equals(returnType)) {

                for (SubmissionSet subSet : rol.getSubmissionSets()) {

                    if (leaf) {

                        RegistryPackageType regPack =
                            this.submissionSetTransformer.transform(subSet);

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createRegistryPackage(regPack));

                    } else {

                        ObjectRefType objRef = new ObjectRefType();

                        objRef.setId(subSet.getEntryURN());

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createObjectRef(objRef));
                    }
                }

            } else if (QueryReturnModelType.Association.equals(returnType)) {

                for (Association assoc : rol.getAssociations()) {

                    if (leaf) {

                        AssociationType1 assocType =
                            this.associationTransformer.transform(assoc);

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createAssociation(assocType));

                    } else {

                        ObjectRefType objRef = new ObjectRefType();

                        objRef.setId(assoc.getEntryURN());

                        result.getIdentifiable().add(
                            XDSUtils.RIMObjectFactory.createObjectRef(objRef));
                    }
                }
            }
        }

        String homeCommunityId = request.getHomeCommunityId();

        if (StringUtils.isNotBlank(homeCommunityId)) {

            // Test 11901 / ITI 3.18.4.13 says we should eat any homeCommunityId
            // Does not say we have to send back a bogus id
            // let's make sure it is right
            homeCommunityId = this.config.getHomeCommunityId();

            // make sure home is set
            List<JAXBElement<? extends IdentifiableType>> idtypes =
                result.getIdentifiable();

            for (JAXBElement<? extends IdentifiableType> idtype : idtypes) {

                idtype.getValue().setHome(homeCommunityId);
            }
        }

        return result;
    }
}
